package com.lhf.azkaban.springbatch.example.job.listener;

import com.lhf.azkaban.springbatch.example.batchreader.RepayOrderFlatFileItemReader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * @Author:95780
 * @Date: 14:23 2019/11/21
 * @Description: map实现的作业执行追踪器
 */
//@Component
public class MapExecutionTracker {
    private static final Logger logger = LogManager.getLogger(MapExecutionTracker.class);
    /**
     * JOB执行信息内存保存数据的最大数量
     */
    private static final Long JOB_EXECUTION_MAX_COUNT = 3000L;
    /**
     * STEP执行信息内存保存数据的最大数量
     */
    private static final Long STEP_EXECUTION_MAX_COUNT = 3000L;
    /**
     * job 执行信息存储
     */
    private Map<Long, JobExecution> jobExecutionMap = new ConcurrentSkipListMap<>();

    /**
     * step 执行信息存储
     */
    private Map<Long, StepExecution> stepExecutionMap = new ConcurrentSkipListMap<>();

    /**
     * 复制作业执行对象
     *
     * @param original
     * @return
     */
    private static JobExecution copyJobExecution(JobExecution original) {
        return (JobExecution) SerializationUtils.deserialize(SerializationUtils.serialize(original));
    }

    /**
     * 保存作业执行对象到内存  最大保存 @seeJOB_EXECUTION_MAX_COUNT 数量
     *
     * @param jobExecution
     */
    public void saveJobExecution(JobExecution jobExecution) {
        if (jobExecution == null) {
            return;
        }
        if (jobExecution.getId() == null || jobExecution.getId() < 1) {
            logger.error("jobExecution id error {}", jobExecution);
            return;
        }
        try {
            //包含最大数量的ID 先删除
            Long removeId = jobExecution.getId() - JOB_EXECUTION_MAX_COUNT;
            if (removeId > 0 && jobExecutionMap.containsKey(removeId)) {
                jobExecutionMap.remove(removeId);
                //JobExecution old = jobExecutionMap.remove(removeId);
                //logger.info("jobExecutionMap remove JobExecution {}",old);
            }

            //如果已经存在则替换，否则添加
            if (jobExecutionMap.containsKey(jobExecution.getId())) {
                jobExecutionMap.replace(jobExecution.getId(), copyJobExecution(jobExecution));
            } else {
                jobExecutionMap.put(jobExecution.getId(), copyJobExecution(jobExecution));
            }
        } catch (Exception e) {
            logger.error("saveJobExecution", e);
        }
    }

    /**
     * 获取作业执行信息
     *
     * @param id
     * @return
     */
    public JobExecution getJobExecutionById(Long id) {
        if (jobExecutionMap != null && jobExecutionMap.containsKey(id)) {
            return copyJobExecution(jobExecutionMap.get(id));
        } else {
            return null;
        }
    }


    /**
     * 保存STEP执行对象到内存
     *
     * @param original
     * @return
     */
    private static StepExecution copyStepExecution(StepExecution original) {
        return (StepExecution) SerializationUtils.deserialize(SerializationUtils.serialize(original));
    }

    /**
     * 保存STEP执行对象到内存  最大保存 @see STEP_EXECUTION_MAX_COUNT 数量
     *
     * @param stepExecution
     */
    public void saveStepExecution(StepExecution stepExecution) {
        if (stepExecution == null) {
            return;
        }
        if (stepExecution.getId() == null || stepExecution.getId() < 1) {
            logger.error("stepExecution id error {}", stepExecution);
            return;
        }
        try {
            //包含最大数量的ID 先删除
            Long removeId = stepExecution.getId() - STEP_EXECUTION_MAX_COUNT;
            if (removeId > 0 && stepExecutionMap.containsKey(removeId)) {
                stepExecutionMap.remove(removeId);
                //StepExecution old = stepExecutionMap.remove(removeId);
                //logger.info("stepExecutionMap remove StepExecution {}",old);

            }

            //如果已经存在则替换，否则添加
            if (stepExecutionMap.containsKey(stepExecution.getId())) {
                stepExecutionMap.replace(stepExecution.getId(), copyStepExecution(stepExecution));
            } else {
                stepExecutionMap.put(stepExecution.getId(), copyStepExecution(stepExecution));
            }
        } catch (Exception e) {
            logger.error("saveStepExecution", e);
        }

    }


    /**
     * 获取step执行信息
     *
     * @param id
     * @return
     */
    public StepExecution getStepExecutionById(Long id) {
        if (stepExecutionMap != null && stepExecutionMap.containsKey(id)) {
            return copyStepExecution(stepExecutionMap.get(id));
        } else {
            return null;
        }
    }


    public void showJobExecutionMap(Long jobExecutionId) {
        if (jobExecutionId == null || !jobExecutionMap.containsKey(jobExecutionId)) {
            for (Long id : jobExecutionMap.keySet()) {
                logger.info(jobExecutionMap.get(id).toString());
            }
        } else {
            logger.info(jobExecutionMap.get(jobExecutionId).toString());
        }
    }


    public void showStepExecutionMap(Long stepExecutionId) {
        if (stepExecutionId == null || !stepExecutionMap.containsKey(stepExecutionId)) {
            for (Long id : stepExecutionMap.keySet()) {
                logger.info(stepExecutionMap.get(id).toString());
            }
        } else {
            logger.info(stepExecutionMap.get(stepExecutionId).toString());
        }
    }
}
